﻿using Common.Device.Enums;
using Common.Device.ViewModels;
using Common.Tool.Models;
using Common.View.Controls.Dialogs;
using HandyControl.Tools.Extension;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using static MaterialDesignThemes.Wpf.Theme.ToolBar;

namespace Common.Device.Models
{
    public class Func : Device
    {
        /// <summary>
        /// 测试模式
        /// </summary>
        public FuncEnum.TestMode mode { get; set; }
        public int 延时时长 { get; set; }
        public string 计算表达式 { get; set; }
        public string 结果单位 { get; set; }
        public int 测试项序号 { get; set; }
        public string 函数编号 { get; set; }
        public string 交互内容 { get; set; }
        public string 提示信息 { get; set; }
        public string 循环设备 { get; set; }
        public string 循环方式 { get; set; }
        public int 最大循环次数 { get; set; }
        public string 跳出方式 { get; set; }
        /// <summary>
        /// 获取测试指令
        /// </summary>
        /// <param name="deviceName">仪器名称</param>
        /// <returns></returns>
        public override Order GetOrder(string deviceName)
        {
            Order order = new Order();
            order.temp = mode.ToString();
            order.name = deviceName;
            switch (mode)
            {
                case FuncEnum.TestMode.延时函数:
                    order.deviceModel = JsonConvert.SerializeObject(new { 延时时长 });
                    break;
                case FuncEnum.TestMode.计算函数:
                    order.range = GetRange(结果单位);
                    order.deviceModel = JsonConvert.SerializeObject(new { 计算表达式, 上限值, 下限值, 结果单位 });
                    break;
                case FuncEnum.TestMode.取值函数:
                    order.deviceModel = JsonConvert.SerializeObject(new { 测试项序号, 函数编号 });
                    break;
                case FuncEnum.TestMode.循环函数:
                    order.deviceModel = JsonConvert.SerializeObject(new { 循环设备, 循环方式, 最大循环次数, 跳出方式 });
                    break;
                case FuncEnum.TestMode.人机交互:
                    order.deviceModel = JsonConvert.SerializeObject(new { 交互内容, 提示信息 });
                    break;
                default:
                    break;
            }
            return order;
        }
        /// <summary>
        /// 测试并返回测试结果
        /// </summary>
        /// <param name="device">仪器实体</param>
        /// <param name="testOrder">测试项指令</param>
        /// <returns></returns>
        public override DeviceResult GetResult(object device, TestOrder testOrder)
        {
            var result = new DeviceResult();
            switch (mode)
            {
                case FuncEnum.TestMode.延时函数:
                    testOrder.document.AppendInfo(mode.ToString(), 延时时长 + "ms");
                    Task.Delay(延时时长).Wait();
                    result.success = true;
                    result.result = "OK";
                    break;
                case FuncEnum.TestMode.计算函数:
                    string math = "";
                    if (testOrder.orders.Count(it => it.state == TestEnum.TestState.失败) > 0)
                    {
                        result.success = false;
                        result.result = "跳过";
                        break;
                    }
                    foreach (var item in 计算表达式)
                    {
                        //将类似 a+b 转换为 1+2
                        //判断是否为参数
                        if (item >= 'a' && item <= 'z')
                        {
                            //根据编号获取对应测试结果
                            var Parameter = testOrder.orders.FirstOrDefault(it => it.no == item.ToString());
                            if (Parameter == null)
                            {
                                result.success = false;
                                result.result = "参数超出范围";
                                return result;
                            }
                            math += Parameter.result.value.ToString();
                        }
                        else
                        {
                            //运算符
                            math += item.ToString();
                        }
                    }
                    try
                    {
                        //计算表达式类似 1+2
                        testOrder.document.AppendInfo(mode.ToString(), "计算" + math);
                        result.value = CSharpScript.EvaluateAsync<double>(math, ScriptOptions.Default.WithImports("System.Math")).Result;
                        result.result = result.value + result.unit;
                        result.success = true;
                        testOrder.document.AppendResult(mode.ToString(), "结果" + result.result);
                    }
                    catch (Exception ex)
                    {
                        result.success = false;
                        result.result = ex.Message;
                        testOrder.document.AppendErr(mode.ToString(), "错误" + result.result);
                        break;
                    }
                    //判断是否在范围内
                    if (下限值 != null && result.success)
                    {
                        result.success = result.value >= 下限值;
                    }
                    if (上限值 != null && result.success)
                    {
                        result.success = result.value <= 上限值;
                    }
                    break;
                case FuncEnum.TestMode.取值函数:
                    testOrder.document.AppendInfo(mode.ToString(), "取值函数" );
                    //测试项序号判断
                    if (testOrder.TestOrders.Count >= 测试项序号)
                    {
                        //获取对应测试项测试结果
                        var Parameter = testOrder.TestOrders[测试项序号 - 1]?.orders.FirstOrDefault(it => it.no == 函数编号.ToString());
                        if (Parameter!=null)
                        {
                            result.value = Parameter.result.value;
                            result.success = true;
                            result.result = "OK";
                            break;
                        }
                    }
                    result.success = false;
                    result.result = "缺失取值数据" + 测试项序号 + 函数编号;                    
                    break;
                case FuncEnum.TestMode.循环函数:
                    //判断设备是否存在
                    if (!DeviceService.useDevices.ContainsKey(循环设备))
                    {
                        result.success = false;
                        result.result = "缺失设备" + 循环设备;
                        break;
                    }
                    testOrder.loopNum = double.Parse(循环方式); //+1 或者 -1
                    testOrder.loopTimes = 最大循环次数;
                    //循环仪器设备
                    testOrder.loopName = 循环设备;
                    result.success = true;
                    result.result = "OK";
                    break;
                case FuncEnum.TestMode.人机交互:
                    var info = (FuncEnum.FuncInfos)Enum.Parse(typeof(FuncEnum.FuncInfos), 交互内容);
                    switch (info)
                    {
                        case FuncEnum.FuncInfos.弹窗确认结果:
                            testOrder.document.AppendInfo(mode.ToString(), 提示信息);
                            //弹窗等待选择
                            Application.Current.Dispatcher.Invoke(() => { 
                                var r1 = TipView.Show(提示信息, new Dictionary<string, Brush> { { "合格", View.Base.Colors.PrimaryColor }, { "不合格", View.Base.Colors.DangerColor } });
                                result.success = r1 == "合格";
                                result.result = r1;
                            }); 
                            testOrder.document.AppendResult(mode.ToString(), "选择" + result.result);
                            break;
                        case FuncEnum.FuncInfos.弹窗输入结果:
                        case FuncEnum.FuncInfos.弹窗扫码:
                            testOrder.document.AppendInfo(mode.ToString(), 提示信息); 
                            //弹窗等待输入
                            Application.Current.Dispatcher.Invoke(() => {
                                var r2 = InputView.Show(提示信息);
                                result.success = !string.IsNullOrEmpty(r2);
                                result.result = r2;
                            });
                            testOrder.document.AppendResult(mode.ToString(), "输入" + result.result);
                            try
                            {
                                if (下限值 != null && result.success)
                                {
                                    result.value = Convert.ToDouble(result.result);
                                    result.success = result.value >= 下限值;
                                }
                                if (上限值 != null && result.success)
                                {
                                    result.value = Convert.ToDouble(result.result);
                                    result.success = result.value <= 上限值;
                                }

                            }
                            catch (Exception ex)
                            {
                                result.success = false;
                                result.result = ex.Message;
                                testOrder.document.AppendErr(mode.ToString(), "错误" + result.result);
                                break;
                            }
                            break;
                        default:
                            break;
                    }
                    break;
                default:
                    break;
            }
            return result; 
        }
    }
}
